home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
commtc2.zip
/
COMM_TC2.C
< prev
next >
Wrap
Text File
|
1993-01-04
|
55KB
|
493 lines
/* */ /*-The comment column will */
/* Written by: Kevin R. Bulgrien Version 1.00 completed 02/01/89 */ /* be used to tell what the */
/* */ /* program is doing where */
/* Contact at: LeTourneau College LeTourneau College BBS */ /* it is not self-evident */
/* Microcomputer Services 2400/1200/300 Baud */ /* */
/* P.O. Box 7001 (214) 237-2742 */ /* Yes, it is wider than 80 */
/* Longview, TX 75607 */ /* columns so you will need */
/* */ /* to use compressed print */
/* This program works with Turbo C 2.0. See Comm_TC2.DOC for instructions. */ /* to print it out */
/* Comm_TP3 & Comm_TP4 by the same author, work with Turbo Pascal 3, 4 & 5 */ /* */
/* Don't complain too much */
/* This program was compiled and tested with the Small Memory Model. Stack */ /* as code documentation is */
/* checking MUST be turned off for the interrupt routine to work correctly. */ /* far easier to read when */
/* it is not intermingled */
/* Version History */ /* with code... */
/* */ /* */
/* 1.00 02/89 Original code uploaded to GEnie's Borland Roundtable */ /* */
/* */
#include <dos.h> /*-The standard headers */
#include <bios.h> /* needed for compilation */
#include <conio.h> /* */
#include <stdio.h> /* */
#include <stdlib.h> /* */
/* */
#define MaxSize 512 /*-Maximum receive buffer */
/* size in bytes */
enum BaudType { B110,B150,B300,B600,B1200,B2400,B4800,B9600,B19200,B38400 }; /*-Baud rates supported */
/* */
enum ParityType { None, Odd, Null, Even, MarkOff, Mark, SpaceOff, Space }; /*-Parity types supported */
/* */
/* Mark parity means that parity is enabled and the parity bit is always set to 0. Space parity means that */
/* parity is enabled and the parity bit is always set to 1. MarkOff and SpaceOff indicate that Mark or */
/* Space parity is chosen but parity is disabled. Functionally they are equivalent to NONE - as is NULL. */
/* */
enum Boolean { FALSE, TRUE }; /*-I like this for storing */
/* logical values */
typedef unsigned char byte; /* */
typedef unsigned int word; /* */
/* */
typedef struct /* 8250 Communications Chip */
{ /* ------------------------ */
word THR; /* Transmit Holding Reg */
word RHR; /* Receive Holding Register */
word DLL; /* Divisor Latch Reg LSB */
word IER; /* Interrupt Enable Reg */
word DLM; /* Divisor Latch Reg MSB */
word IIR; /* Interrupt ID Register */
word LCR; /* Line Control Register */
word MCR; /* Modem Control Register */
word LSR; /* Line Status Register */
word MSR; } INS8250 [2]; /* Modem Status Register */
/* */
typedef struct /*-Used to hold the current */
{ /* settings of COM1 & COM2 */
byte Baud; /* */
byte Parity; /* */
byte Stop; /* */
byte Bits; } ComSettingsType [2]; /* */
/* */
const INS8250 RS232 = { /*-COM1 addresses for 8250 */
{ 0x3F8, 0x3F8, 0x3F8, 0x3F9, 0x3F9, /* registers so they may be */
0x3FA, 0x3FB, 0x3FC, 0x3FD, 0x3FE /* accessed by name */
}, /* */
{ 0x2F8, 0x2F8, 0x2F8, 0x2F9, 0x2F9, /*-COM2 addressed for 8250 */
0x2FA, 0x2FB, 0x2FC, 0x2FD, 0x2FE /* registers so they may be */
} /* accessed by name */
}; /* */
/* */
void interrupt (*OldIntVector [2]) (); /*-Original COMx vectors */
enum Boolean IntInstalled [2]; /*-TRUE if interrupt loaded */
word InHead [2], InTail [2]; /*-Input buffer indexes */
ComSettingsType ComSettings; /*-COMx line settings */
byte InBuffer [2] [MaxSize]; /*-Input circular queue */
enum Boolean Carrier [2]; /*-TRUE if Carrier Detected */
byte CurrentCom; /*-COM port in use */
word MaxPorts; /*-# of usable COM ports */
/* */
/* This procedure sets up the selected COM port to the specified parameters. The Com parameter specifies */
/* the port to set up. It must be in the range 0 to 1, and is checked for errors. The Baud parameter must */
/* be in the range 0 to 9, and is not range checked. 1.5 stop bits are used when StopBits == 2 AND DataBits */
/* == 5, but otherwise StopBits will set the correct number of stop bits in the range 1 to 2. DataBits may */
/* be set with 5 to 8 for the number of data bits to use. */
/* */
void SetupRS232 (byte Com, byte Baud, byte Parity, byte StopBits, byte DataBits)/* */
{ /*-These values set a baud */
const word BaudTable [] = { 0x0417, 0x0300, 0x0180, 0x00C0, 0x0060, /* rate for the 8250 when */
0x0030, 0x0018, 0x000C, 0x0006, 0x0003 }; /* written to DLL & DLM */
byte Parameters; /*-Temporary to calculate */
/* LCR register setting */
if (Com < MaxPorts) /*-Check validity of Com */
{ /* */
disable (); /*-Always when writing 8250 */
outportb (RS232 [Com].MCR, 0x00); /*-DTR & RTS off/kill modem */
outportb (RS232 [Com].LCR, inportb (RS232 [Com].LCR) | 0x80); /*-Allow access to DLL/DLM */
outportb (RS232 [Com].DLL, BaudTable [Baud] & 0x00FF); /*-Set baud rate */
outportb (RS232 [Com].DLM, (BaudTable [Baud] & 0xFF00) >> 0x08); /* */
Parameters = (DataBits - 5) & 0x03; /*-Build values to write to */
Parameters = Parameters | (((StopBits - 1) << 2) & 0x04); /* Line Control Register */
Parameters = Parameters | ((Parity << 3) & 0x38); /* */
outportb (RS232 [Com].LCR, Parameters); /*-Set Parity/Data/Stop Bits*/
outportb (RS232 [Com].MCR, 0x0B); /*-DTR & RTS back on */
enable (); /*-Done writing to 8250 Regs*/
} /* */
else printf ("\nError! COM%u not available/n", Com); /*-Used for debugging while */
} /* writing an application */
/* */
/* This procedure handles interrupts from the 8250 communications chip. All interrupt types are provided */
/* for though I only implemented the receive data interrupt and crudely used the modem status interrupt. */
/* The skeleton is there though, so you can write your own implementations for the interrupts. Incoming */
/* data is stored in InBuffer if the buffer is not full - otherwise it is ignored. The buffer is full when */
/* (InTail [IntCom] + 1) % MaxSize == InHead [IntCom]. The buffer is empty when InTail [IntCom] == InHead */
/* [IntCom]. InTail [IntCom] is incremented so that it always points to where the next item will be put. */
/* Modem (port) status is monitored for Carrier Detect. The global enum Boolean variable 'Carrier' always */
/* shows the status of each COM port if its interrupt handler is active. TRUE == Carrier Detected and */
/* FALSE == No Carrier Detected. This is done for programs that will use a modem for input. NOTE: Stack */
/* checking must always be turned off in interrupt handlers. */
/* */
void interrupt IntHandler () /* */
{ /* */
byte IntCom; /*-COM port which caused an */
/* interrupt */
outportb (0x20, 0x0B); /*-Allow access to 8259 ISR */
IntCom = (2 - ((inportb (0x20) & 0x18) >> 3)); /*-Detect interrupting port */
switch (inportb (RS232 [IntCom].IIR) & 0x06) /* */
{ /* */
case 0 : Carrier[IntCom] = (0x80 & inportb(RS232[IntCom].MSR)); /*-Modem Status Change Int. */
break; /*-Save new Carrier status */
case 2 : /* DO Nothing */; /*-Transmit Register empty */
break; /*-Receive Register full */
case 4 : outportb(RS232[IntCom].LCR,inportb(RS232[IntCom].LCR) & 0x7F); /*-Allow THR/RHR/IER access */
if (((InTail [IntCom] + 1) % MaxSize) != InHead [IntCom]) /* */
{ /*-If buffer is not full, */
InBuffer[IntCom][InTail[IntCom]] = inportb (RS232[IntCom].RHR);/* add the character & set */
InTail [IntCom] = (InTail [IntCom] + 1) % MaxSize; /* the queue index pointer */
} /* */
else if (inportb (RS232 [IntCom].RHR) == 0x00) /* DO Nothing */; /*-If the buffer is full, */
break; /* read & ignore character */
case 6 : /* DO Nothing */; /* */
break; /*-Line Status Change Int. */
} /* */
outportb (0x20, 0x20); /*-Notify 8259 of interrupt */
} /* completion (nonspecific) */
/* */
/* This procedure installs and enables the specified serial port interrupt. It also forces the appropriate */
/* input buffer to the empty state. Carrier is initialized to the current state of the Carrier Detect line */
/* on the port. The old serial port interrupt vector is saved so that it can be reinstalled when we remove */
/* our serial port interrupt. DTR and RTS are forced to the ready state & the 8250 interrupts are enabled */
/* by writing 0x0B to the MCR. To enable all four types of 8250 interrupts, write 0x0F to the IER. (I used */
/* 0x09 to only enable the Modem Status Change and Receive Buffer Full interrupts). ORing 0xEF with I/O */
/* port 0x21 enables IRQ4 (COM1), while ORing 0xF7 enables IRQ3 (COM2). Interrupts must be disabled during */
/* the installation process since the 8250 & 8259 ports are being accessed. */
/* */
void InstallInt (byte Com) /* */
{ /*-Don't install twice or */
if ((! IntInstalled [Com]) && (Com < MaxPorts)) /* install for missing port */
{ /* */
disable (); /* */
InTail [Com] = 0; /*-Force input buffer empty */
InHead [Com] = 0; /* */
Carrier [Com] = ((0x80 & inportb (RS232 [Com].MSR)) == 0x80); /*-Read Carrier Status */
outportb (RS232 [Com].LCR, inportb (RS232 [Com].LCR) & 0x7F); /*-Allow THR/RHR/IER access */
outportb (RS232 [Com].IER, 0x00); /*-Disable 8250 interrupts */
if (inportb (RS232 [Com].LSR) != 0) /* Nothing */; /*-Reset interrupts waiting */
if (inportb (RS232 [Com].RHR) != 0) /* Nothing */; /* to be processed */
OldIntVector [Com] = getvect (0x0C - Com); /*-Save old interrupt vector*/
setvect (0x0C - Com, IntHandler); /*-Load new interrupt vector*/
IntInstalled [Com] = TRUE; /* */
switch (Com) /* */
{ /* */
case 0 : outportb (0x21, inportb (0x21) & 0xEF); /*-Enable 8259 IRQ4 (COM1) */
break; /* */
case 1 : outportb (0x21, inportb (0x21) & 0xF7); /*-Enable 8259 IRQ3 (COM2) */
default : break; /* */
} /* */
outportb (RS232 [Com].LCR, inportb (RS232 [Com].LCR) & 0x7F); /*-Allow THR/RHR/IER access */
outportb (RS232 [Com].IER, 0x09); /*-Enable 8250 interrupts */
outportb (RS232 [Com].MCR, 0x0B); /*-Set DTR & RTS so other */
enable (); /* device knows we're ready */
} /* to receive data */
else /* */
{ /* */
printf ("\nError! COM%u ", Com + 1); /*-Here for debugging use */
if (IntInstalled [Com]) /* Remove it if you want to */
puts ("interrupt already installed\n"); /* */
else /* */
puts ("not available\n"); /* */
} /* */
} /* */
/* */
/* This procedure removes the specified serial port interrupt & reinstalls the original interrupt vectors. */
/* DTR & RTS are set OFF and 8250 interrupts are disabled by writing 0x00 to the MCR. All 8250 interrupt */
/* type are disabled by writing 0x00 to the IER. ORing 0x10 with I/O port 0x21 disables IRQ4 (COM1), while */
/* ORing 0x08 disables IRQ3 (COM2). Interrupts must be disabled during this process. */
/* */
void RemoveInt (byte Com) /* */
{ /* */
if (IntInstalled [Com]) /*-Do not remove interrupt */
{ /* if it was not installed */
disable (); /* */
switch (Com) /* */
{ /* */
case 0 : outportb (0x21, inportb (0x21) | 0x10); /*-Disable 8259 IRQ4 (COM1) */
break; /* */
case 1 : outportb (0x21, inportb (0x21) | 0x08); /*-Disable 8259 IRQ3 (COM2) */
break; /* */
} /* */
outportb (RS232 [Com].LCR, inportb (RS232 [Com].LCR) & 0x7F); /*-Allow THR/RHR/IER access */
outportb (RS232 [Com].IER, 0x00); /*-Disable 8250 interrupts */
outportb (RS232 [Com].MCR, 0x00); /*-Set DTR/RTS off. Remove */
setvect (0x0C - Com, OldIntVector [Com]); /* if modem shouldn't hang */
IntInstalled [Com] = FALSE; /* up when you RemoveInt */
enable (); /*-setvect installed the */
} /* original interrupt vector*/
else printf ("\nError! COM%u interrupt is not installed\n", Com+1); /*-Used for debugging. It */
} /* is optional. */
/* */
/* This procedure writes character or string data to the serial port. It does this by directly reading and */
/* writing to the 8250 communications chip. This is an example that may be modified to suit your purposes. */
/* As is, it pauses the program while it sends the data. If it cannot send a character after 65535 tries, */
/* it aborts the sending process. This could easily be converted to a function that returns a enum Boolean */
/* value TimeOut. The statement: (inportb (RS232 [Com].LSR) & 0x20) != 0x20 indicates when the THR is ready */
/* for a new character to send. CTS and DSR are not checked, but if you want to check for them (inportb */
/* (RS232 [Com].MSR) & 0x30) must equal 0x30. Interrupts must be disabled while using the 8250 ports. Com */
/* is 0 for COM1 and 1 for COM2. DataPtr is a pointer to a string. */
/* */
void WriteCOM (byte Com, byte *DataPtr) /* */
{ /* */
enum Boolean TimeOut; /*-TRUE if unable to send */
word TimeLoop; /*-Timeout counter */
/* */
TimeOut = FALSE; /* */
while (*DataPtr && ! TimeOut) /*-Send data one char at a */
{ /* time unless timed out */
TimeLoop = 0; /* */
while ((TimeLoop < 0xFFFF)&&((inportb (RS232 [Com].LSR) & 0x20) != 0x20)) /*-Do not send data if THR */
TimeLoop += 1; /* is not empty yet */
if (TimeLoop != 0xFFFF) /* */
{ /* */
disable (); /* */
outportb (RS232 [Com].LCR, inportb (RS232 [Com].LCR) & 0x7F); /*-Allow THR/RHR/IER access */
outportb (RS232 [Com].THR, *DataPtr); /*-Put data to send in THR */
enable (); /* */
DataPtr++; /*-Advance string pointer */
} /* */
else /* */
{ /* */
TimeOut = TRUE; /*-WriteCOM aborts if THR */
printf ("\nTimeout on COM%u", Com); /* takes too long to become */
} /* empty */
} /* */
} /* */
/* */
/* This function is an example of how to get a character from the serial port. As is, when the buffer is */
/* empty, it waits until a character arrives, so this will not work for the TTY emulation. The interrupts */
/* are always disabled when the buffer pointers are checked or modified. Beware! Do not completely disable */
/* interrupts in the wait loop or else you never will get a character if there is not one there already. */
/* */
byte ReadCOM (byte Com) /* */
{ /* */
enum Boolean CharReady; /*-TRUE if there is data */
byte DataByte; /*-Data buffer */
/* */
CharReady = FALSE; /* */
do /*-Wait for data to arrive */
{ /* */
disable (); /* */
CharReady = (InTail [Com] != InHead [Com]); /*-Check if the buffer is */
enable (); /* empty or not */
} while (! CharReady); /* */
disable (); /* */
DataByte = InBuffer [Com] [InHead [Com]]; /*-Read the character */
InHead [Com] = (InHead [Com] + 1) % MaxSize; /*-Remove it from the input */
enable (); /* buffer */
return (DataByte); /*-Return the character */
} /* */
/* */
atexit_t RemoveIntOnExit (void) /*-VERY IMPORTANT! When the */
{ /* program quits normally */
if (IntInstalled [0]) RemoveInt (0); /* or abnormally, interrupt */
if (IntInstalled [1]) RemoveInt (1); /* handlers are uninstalled */
printf ("\nAll interrupt handlers have been uninstalled\n"); /* automatically */
} /* */
/* */
/* End of RS-232 handler routines ---------- Start of TTY emulation routines */ /* */
/* */
/* A crude but effective procedure to allow the user to change settings of a COM port in use. CurrentCom */
/* and ComSettings determine how the port is currently set up. As the parameters are changed, ComSettings */
/* updated. Once again, keep in mind that the object of this program is not to provide a glamorous terminal */
/* program. Rather it serves as a simple model for those wanting to incorporate serial routines in their */
/* own programs. */
/* */
void SetUpPort (byte Com) /* */
{ /* */
enum Boolean ResetPort; /*-TRUE if settings changed */
byte InkeyChr; /*-Keyboard input variable */
/* */
ResetPort = FALSE; /* */
printf ("\nCOM%u Setup\n\n", Com + 1); /*-Identify port to change */
puts ("0) 110 5) 2400\n1) 150 6) 4800"); /* */
puts ("2) 300 7) 9600\n3) 600 8) 19200"); /*-Select a baud rate */
puts ("4) 1200 9) 38400\n"); /* */
printf ("Select a baud rate [%u]: ", ComSettings [Com] . Baud); /*-Note that defaults are */
do /* allowed if you use <CR> */
{ /* at any of the prompts. */
InkeyChr = (byte) getch (); /* The port is not reset */
} while (((InkeyChr < 48) | (InkeyChr > 57)) & (InkeyChr != 0x0D)); /* unless the defaults are */
printf ("%c\n\n", (byte) InkeyChr); /* changed */
if (InkeyChr != 0x0D) /* */
{ /* */
ComSettings [Com] . Baud = InkeyChr - 48; /* */
ResetPort = TRUE; /* */
} /* */
puts ("0) None 2) None\n1) Odd 3) Even\n"); /*-Select a parity setting */
printf ("Select a parity type [%u]: ", ComSettings [Com] . Parity); /* */
do /* */
{ /* */
InkeyChr = (byte) getch (); /* */
} while (((InkeyChr < 48) | (InkeyChr > 51)) & (InkeyChr != 0x0D)); /* */
printf ("%c\n\n", (byte) InkeyChr); /* */
if (InkeyChr != 0x0D) /* */
{ /* */
ComSettings [Com] . Parity = InkeyChr - 48; /* */
ResetPort = TRUE; /* */
} /* */
printf ("Select number of stop bits [%u]: ", ComSettings [Com] . Stop); /*-Set the number of stop */
do /* bits to use */
{ /* */
InkeyChr = (byte) getch (); /* */
} while (((InkeyChr < 49) | (InkeyChr > 50)) & (InkeyChr != 0x0D)); /* */
printf ("%c\n\n", (byte) InkeyChr); /* */
if (InkeyChr != 0x0D) /* */
{ /* */
ComSettings [Com] . Stop = InkeyChr - 48; /* */
ResetPort = TRUE; /* */
} /* */
printf ("Select number of data bits [%u]: ", ComSettings [Com] . Bits); /*-Set the number of data */
do /* bits to use */
{ /* */
InkeyChr = (byte) getch (); /* */
} while (((InkeyChr < 53) | (InkeyChr > 56)) & (InkeyChr != 0x0D)); /* */
printf ("%c\n\n", (byte) InkeyChr); /* */
if (InkeyChr != 0x0D) /* */
{ /* */
ComSettings [Com] . Bits = InkeyChr - 48; /* */
ResetPort = TRUE; /* */
} /* */
if (ResetPort) /*-If any of the settings */
SetupRS232 (Com, ComSettings [Com] . Baud, /* have changed, reset the */
ComSettings [Com] . Parity, /* port */
ComSettings [Com] . Stop, /* */
ComSettings [Com] . Bits); /* */
} /* */
/* */
/* This provides a simple terminal emulation that might be used to prove that these routines really work, */
/* that they are not hard to use. I got to playing, and perhaps it got a bit more complex than necessary... */
/* but then again, who said it had to be quick and dirty. The LocalEcho parameter determines if characters */
/* typed on the keyboard should be echoed to the screen. */
/* */
void TTY (enum Boolean LocalEcho) /* */
{ /* */
enum Boolean ExitTTY; /*-TRUE when ready to quit */
enum Boolean DataReady; /*-TRUE if buffer not empty */
enum Boolean OldCarrier [2]; /*-Detects Carrier change */
byte Buffer [3]; /*-Character buffer string */
/* */
OldCarrier [0] = ! Carrier [0]; /*-Force Carrier Detect */
OldCarrier [1] = ! Carrier [1]; /* status to be displayed */
DataReady = FALSE; /* */
ExitTTY = FALSE; /* */
clrscr (); /* */
puts ("Terminal emulator commands\n"); /*-Brief summary of command */
puts ("<ALT C> Toggle Port in use COM1/2"); /* keys that can be used */
puts ("<Alt E> Toggle Local Echo On/Off"); /* */
puts ("<Alt P> Change Port Parameters"); /* */
puts ("<Alt X> Exit\n"); /* */
printf ("%u port(s) available\n", MaxPorts); /* */
do /*-Terminal emulation start */
{ /* */
disable (); /*-If data is received, */
DataReady = (InTail [CurrentCom] != InHead [CurrentCom]); /* print it one char per */
enable (); /* pass through the loop */
if (DataReady) /* */
{ /* */
disable (); /* */
Buffer [0] = InBuffer [CurrentCom] [InHead [CurrentCom]]; /* */
InHead [CurrentCom] = (InHead [CurrentCom] + 1) % MaxSize; /* */
enable (); /* */
switch (Buffer [0]) /* */
{ /* */
case 12 : clrscr (); /*-Formfeed clears the */
break; /* terminal screen */
default : putch (Buffer [0]); /* */
break; /* */
} /* */
} /* */
if (OldCarrier [CurrentCom] != Carrier [CurrentCom]) /*-Display any changes in */
{ /* Carrier Detect status */
if (Carrier [CurrentCom]) /* */
printf ("\nCARRIER DETECTED (COM%u)\n", CurrentCom + 1); /* */
else /* */
printf ("\nNO CARRIER (COM%u)\n", CurrentCom + 1); /* */
OldCarrier [CurrentCom] = Carrier [CurrentCom]; /* */
} /* */
if (kbhit ()) /*-If a key has been pushed */
{ /* then process it */
Buffer [0] = getch(); /* */
if ((Buffer [0] == 0) && kbhit()) /*-Extended key codes need */
{ /* another read */
Buffer [0] = getch(); /* */
switch (Buffer [0]) /*-Process function keys */
{ /* */
case 46 : if (((CurrentCom + 1) % 2 ) < MaxPorts) /*-<ALT C> lets you toggle */
{ /* between ports if both */
CurrentCom = (CurrentCom + 1) % 2; /* ports exist */
printf ("\nCOM%u\n", CurrentCom + 1); /* */
} /* */
else /* */
{ /* */
printf ("\nCOM%u not available\n", 1+(CurrentCom + 1) % 2); /* */
} /* */
break; /* */
case 18 : LocalEcho = ! LocalEcho; /*-<ALT E> toggles duplex */
break; /* */
case 25 : SetUpPort (CurrentCom); /*-<ALT P> for port setup */
break; /* */
case 45 : ExitTTY = TRUE; /*-<ALT X> exits emulation */
break; /* */
default : Buffer [1] = Buffer [0]; /*-All other function keys */
Buffer [0] = '\x1B'; /* are passed through to */
Buffer [2] = '\x00'; /* the port */
WriteCOM (CurrentCom, Buffer); /* */
break; /* */
} /* */
} /* */
else /*-Normal keys are sent or */
{ /* translated and then sent */
Buffer [1] = '\x00'; /* */
switch (Buffer [0]) /* */
{ /* */
case 12 : if (LocalEcho) clrscr (); /*-FormFeed clears screen */
break; /* if local echo is on */
case 13 : Buffer [1] = '\x0A'; /*-Linefeed added to <CR> */
Buffer [2] = '\x00'; /* */
if (LocalEcho) puts (""); /* */
break; /* */
default : if (LocalEcho) putch (Buffer [0]); /* */
break; /*-All other characters are */
} /* sent as typed */
WriteCOM (CurrentCom, Buffer); /* */
} /*-Send the buffered data */
} /* */
} while (! ExitTTY); /* */
} /*-Continue emulation until */
/* <ALT X> is pressed */
main () /* */
{ /* */
clrscr (); /* */
atexit ((atexit_t) RemoveIntOnExit); /*-VERY IMPORTANT! */
MaxPorts = (biosequip () & 0x0E00) >> 9; /*-How many ports there are */
IntInstalled [0] = FALSE; /*-No interrupt handlers */
IntInstalled [1] = FALSE; /* are installed yet */
ComSettings [0] . Baud = B9600; /*-Define COM1 default */
ComSettings [0] . Parity = None; /* protocol settings */
ComSettings [0] . Stop = 1; /* */
ComSettings [0] . Bits = 8; /* */
ComSettings [1] . Baud = B2400; /*-Define COM2 default */
ComSettings [1] . Parity = None; /* protocol settings */
ComSettings [1] . Stop = 1; /* */
ComSettings [1] . Bits = 8; /* */
if (MaxPorts > 0) /*-If COM1 exists: */
{ /* */
SetupRS232 (0, ComSettings [0] . Baud, /*-Initialize COM1 to the */
ComSettings [0] . Parity, /* default settings */
ComSettings [0] . Stop, /* */
ComSettings [0] . Bits); /* */
InstallInt (0); /*-Install the interrupt */
} /* */
else puts ("Error! No serial ports installed in this computer"); /* */
if (MaxPorts > 1) /*-If COM2 exists: */
{ /* */
SetupRS232 (1, ComSettings [1] . Baud, /*-Initialize COM2 to the */
ComSettings [1] . Parity, /* default settings */
ComSettings [1] . Stop, /* */
ComSettings [1] . Bits); /* */
InstallInt (1); /*-Install the interrupt */
} /* */
CurrentCom = 0; /*-Set COM1 as logged port */
TTY (FALSE); /*-TTY with local echo off */
/* */
/* IMPORTANT: RemoveIntOnExit is always called when the program terminates! */ /*-RemoveIntOnExit invoked */
/* by Turbo C. Don't exit */
} /* w/o removing interrupts! */